home *** CD-ROM | disk | FTP | other *** search
/ PC Graphics Unleashed / PC Graphics Unleashed.iso / ch05 / equalize.c < prev    next >
C/C++ Source or Header  |  1994-08-07  |  30KB  |  730 lines

  1. /*..............................   EQUALIZE.C ................. 7-31-94 ....*/
  2. /*                   Histogram Equalization demo program.                   */
  3. /*..........................................................................*/
  4. #include <stdio.h>     
  5. #include<conio.h>
  6. #include<math.h>
  7. #include<limits.h>
  8. #include<malloc.h>
  9.  
  10. #include <tiff.h>           /* Required to support TIFF256 Graphics Library */
  11. #include <vsa.h>            /* Required to support VSA256 Graphics Library  */
  12. #include <vsa_font.h>       /* Required to support VSA256 Graphics Library  */
  13.  
  14. #ifndef _MSC_VER
  15. /*.....                This is line for Borland C Only !               .....*/
  16. extern unsigned _stklen = 13000;
  17. #endif
  18.  
  19. void show_hist(int,int,long *,float);
  20. void hist_image(unsigned char huge *, unsigned char *, long *, int);
  21. void hist_display(int, int, int, int, unsigned char *, long *, int);
  22. void histeq(unsigned char *,long *,double, int);
  23. int  image_stats(int, int);
  24. void color_bar(int,int);
  25. void update_message(int,int,int,char *);
  26. void clear_text_area(int,int,int,int);
  27. void vsa_get_input(char *);
  28. void error_message(int,int,int,int);
  29.  
  30. void main(int argc, char *argv[])
  31. {
  32.     int a,b,r0,c0,i,error,vmode;
  33.     long hist[256],save_hist[256];
  34.     unsigned xx,yy,x0,y0;
  35.     char filename[100],text[100], key;
  36.     unsigned char lut[768], save_lut[768];
  37.     double power;
  38.     x0 = 3;
  39.     y0 = 3;
  40.     if(argc > 1)
  41. /*.............................................................*/
  42. /*          If specified, set requested video  mode.           */
  43. /*.............................................................*/
  44.         {
  45.             sscanf(argv[1],"%x",&vmode);
  46.             if(vsa_init(vmode) != 0)
  47.                     {
  48.                         printf("Can't set Requested VESA video mode!\n");
  49.                         printf("Is VESA BIOS Extension TSR loaded?\n");
  50.                         return;
  51.                     }
  52.         }
  53.     else
  54. /*.............................................................*/
  55. /*     Otherwise set highest video resolution available.       */
  56. /*.............................................................*/
  57.         {
  58.             if(vsa_init(0x105) != 0)             /* 1024 x 768 x 256 */
  59.                 if(vsa_init(0x103) != 0)           /*  800 x 600 x 256 */
  60.                     if(vsa_init(0x101) != 0)         /*  640 x 480 x 256 */
  61.                         if(vsa_init(0x100) != 0)       /*  640 x 400 x 256 */
  62.                             {
  63.                                 printf("Can't set VESA video mode!\n");
  64.                                 printf("Is VESA BIOS Extension TSR loaded?\n");
  65.                                 return;
  66.                             }
  67.         }
  68.     xx = XResolution;
  69.     yy = YResolution;
  70.     vsa_set_text_cursor_mode(1);
  71.     r0 = 0.85*YCharResolution;
  72.     c0 = 0.5*XCharResolution - 17;
  73. /*..........................................................................*/
  74. /*  Set the color look up table with a 8 bit RGB palette and also set       */
  75. /*  the prime colors.                                                       */
  76. /*..........................................................................*/
  77.     tf_set_true_color_mode(2,255,50);
  78.     tf_set_prime_colors();
  79. /*..........................................................................*/
  80. /*                        Draw Frame around screen.                         */
  81. /*..........................................................................*/
  82.     vsa_set_color(TF_Blue);
  83.     vsa_move_to(0,0);
  84.     vsa_rect(XResolution-1,YResolution-1);
  85. HERE:
  86.     a = .125*xx;
  87.     b = .91*yy;
  88.     color_bar(a,b);
  89. /*..........................................................................*/
  90. /*         Wait for any key to continue; if ESC key, quit program.          */
  91. /*..........................................................................*/
  92.     update_message(c0*XCharSize,r0*YCharSize,TF_Yellow,
  93.                                      "Press ESC to exit, Any other key to continue ...   ");
  94.     key = getch();
  95.     if(key == 27)
  96.         goto BAIL;
  97.     update_message(c0*XCharSize,(r0-1)*YCharSize,TF_Red,"                                                ");
  98. /*..........................................................................*/
  99. /*                            Open TIFF File.                               */
  100. /*..........................................................................*/
  101. FILENAME:
  102.     update_message(c0*XCharSize,r0*YCharSize,TF_Green,"Input full Filename: ");
  103.     vsa_get_input(filename);
  104.     error = tf_open_file(filename);
  105.     if(error == -1)
  106.         {
  107.             update_message(c0*XCharSize,(r0-1)*YCharSize,TF_Red,"Can't Find Specified File! ... Try Again.   ");
  108.             goto HERE;
  109.         }
  110. /*..........................................................................*/
  111. /*                      Get TIFF File information.                          */
  112. /*                 Also Provide friendly error messages!                    */
  113. /*..........................................................................*/
  114.     error = tf_get_file_info();
  115.     if(error)
  116.         {
  117.             error_message(0,error,c0,r0-1);
  118.             goto NOTSUPPORTED;
  119.         }
  120. /*..........................................................................*/
  121. /*  Prior to reading the image information, set defaults for all globals.   */
  122. /*..........................................................................*/
  123.     tf_set_defaults();
  124. /*..........................................................................*/
  125. /* Read image information.  Globals are set, pointers to image data are     */
  126. /* extracted. Also Provide friendly error messages!                         */
  127. /*..........................................................................*/
  128.     error = tf_read_ifd();
  129.     if(error)
  130.         {
  131.             error_message(1,error,c0,r0-1);
  132.             goto NOTSUPPORTED;
  133.         }
  134. /*..........................................................................*/
  135. /*                 Display TIFF image starting at (x0,y0).                  */
  136. /*..........................................................................*/
  137.     if(TF_SamplesPerPixel == 3)
  138.         update_message(c0*XCharSize,(r0-1)*YCharSize,TF_Red,"Please Wait - Calculating ADAPTIVE Palette.     ");
  139.     if(tf_display_ifd(x0,y0) != 0)
  140.         {
  141.             update_message(c0*XCharSize,(r0-1)*YCharSize,TF_Red,"Low Memory: Turning Adaptive Palette OFF!       ");
  142.             tf_set_true_color_mode(1,255,50);
  143.             tf_display_ifd(x0,y0);
  144.             tf_set_true_color_mode(2,255,50);
  145.         }
  146.     update_message(c0*XCharSize,(r0-1)*YCharSize,TF_Red,"                                                ");
  147. /*..........................................................................*/
  148. /*                 Restore Prime Color Values.                              */
  149. /*..........................................................................*/
  150.     tf_set_prime_colors();
  151. /*..........................................................................*/
  152. /*                            Frame new image.                              */
  153. /*..........................................................................*/
  154.     vsa_set_color(TF_White);
  155.     vsa_move_to(x0-2,y0-2);
  156.     vsa_rect(x0+(unsigned)TF_ImageWidth+1,y0+(unsigned)TF_ImageLength+1);
  157.     vsa_set_color(TF_Black);
  158.     vsa_move_to(x0-1,y0-1);
  159.     vsa_rect(x0+(unsigned)TF_ImageWidth,y0+(unsigned)TF_ImageLength);
  160. /*..........................................................................*/
  161. /*                      Redraw Frame around screen.                         */
  162. /*..........................................................................*/
  163.     vsa_set_color(TF_Blue);
  164.     vsa_move_to(0,0);
  165.     vsa_rect(XResolution-1,YResolution-1);
  166. /*..........................................................................*/
  167. /*                 Update Image Statistics                                  */
  168. /*..........................................................................*/
  169.     image_stats(XResolution - 255,150);
  170. /*..........................................................................*/
  171. /*                Compute Histogram of image and display.                   */
  172. /*..........................................................................*/
  173.     vsa_read_color_block(0,256,save_lut);
  174.     hist_display(x0,y0,(int)(x0+TF_ImageWidth-1),(int)(y0+TF_ImageLength-1),
  175.                              save_lut,save_hist,0);
  176.     show_hist(XResolution-258,3,save_hist,0.3);
  177.     update_message(c0*XCharSize,(r0+1)*YCharSize,TF_White,"Hit any key to Equalize.          ");
  178.     getch();
  179.     update_message(c0*XCharSize,(r0+2)*YCharSize,TF_White,"Hit Up/Down arrows to change 'Power', ESC to Quit.");
  180.     power = 0.0;
  181.     key = 0;
  182.     while(key != 27)
  183.         {
  184.             for(i=0;i<768;i++)
  185.                 lut[i] = save_lut[i];
  186.             for(i=0;i<256;i++)
  187.                 hist[i] = save_hist[i];
  188.             histeq(lut,hist,power,0);
  189.             vsa_write_color_block(0,256,lut);
  190.             tf_set_prime_colors();      /* Should do this whenever LUT is reloaded*/
  191.             show_hist(XResolution-258,3,hist,0.3);
  192.             sprintf(text,"Equalized with 'Power' = %f          ",power);
  193.             update_message(c0*XCharSize,(r0+1)*YCharSize,TF_White,text);
  194.             key = getch();
  195.             if((key == 0) || (key == 0xe))
  196.                 {
  197.                     key = getch();
  198.                     if(key == 72) power += 0.1;
  199.                     if(key == 80) power -= 0.1;
  200.                     if(power > 4.0) power = 4.0;
  201.                     if(power < -4.0) power = -4.0;
  202.                 }
  203.         }
  204.     update_message(c0*XCharSize,(r0+1)*YCharSize,TF_White,"Saving Image as NEW.TIF           ");
  205.     update_message(c0*XCharSize,(r0+2)*YCharSize,TF_White,"                                  ");
  206.     tf_save_file(x0,y0,x0+(int)TF_ImageWidth-1,y0+(int)TF_ImageLength-1,
  207.                              "new.tif");
  208.     update_message(c0*XCharSize,(r0+1)*YCharSize,TF_White,"                                  ");
  209. /*..........................................................................*/
  210. /*                        Close opened TIFF file.                           */
  211. /*..........................................................................*/
  212. NOTSUPPORTED:
  213.     tf_close_file();
  214.     goto HERE;
  215. /*..........................................................................*/
  216. /*                       Restore text video mode and Bail Out.              */
  217. /*..........................................................................*/
  218. BAIL:
  219.     vsa_set_svga_mode(0x3);
  220.     tf_about();
  221.     getch();
  222.     vsa_init(0x3);
  223.     return;                       /*.....            End main            .....*/
  224. }
  225.  
  226.  
  227. image_stats(int x0,int y0)
  228. {
  229.     char text[100];
  230.     unsigned char row,col;
  231.  
  232.     row = y0/YCharSize;
  233.     col = x0/XCharSize;
  234.  
  235.     sprintf(text,"Width  = %d     ",TF_ImageWidth);
  236.     update_message(col*XCharSize,row*YCharSize,TF_White,text);
  237.     row++;
  238.     sprintf(text,"Length = %d     ",TF_ImageLength);
  239.     update_message(col*XCharSize,row*YCharSize,TF_White,text);
  240.     row++;
  241.     if(TF_PhotometricInterpretation < 2)
  242.         {
  243.             update_message(col*XCharSize,row*YCharSize,TF_White,"Color Model = Bilevel or");
  244.             row++;
  245.             update_message(col*XCharSize,row*YCharSize,TF_White,"              GrayScale ");
  246.             row++;
  247.             sprintf(text,"%d Bits Per Pixel        ",TF_BitsPerSample[0]);
  248.             update_message(col*XCharSize,row*YCharSize,TF_White,text);
  249.             row++;
  250.         }
  251.     if(TF_PhotometricInterpretation == 2)
  252.         {
  253.             update_message(col*XCharSize,row*YCharSize,TF_White,"Color Model = True Color");
  254.             row++;
  255.             update_message(col*XCharSize,row*YCharSize,TF_White,"24 Bits Per Pixel       ");
  256.             row++;
  257.             update_message(col*XCharSize,row*YCharSize,TF_White,"(8 bits each R,G,B)     ");
  258.             row++;
  259.         }
  260.     if(TF_PhotometricInterpretation == 3)
  261.         {
  262.             update_message(col*XCharSize,row*YCharSize,TF_White,"Color Model = Palette   ");
  263.             row++;
  264.             sprintf(text,"%d Bits Per Pixel        ",TF_BitsPerSample[0]);
  265.             update_message(col*XCharSize,row*YCharSize,TF_White,text);
  266.             row++;
  267.             update_message(col*XCharSize,row*YCharSize,TF_White,"                        ");
  268.             row++;
  269.         }
  270.     if(TF_PhotometricInterpretation > 3)
  271.         update_message(col*XCharSize,row*YCharSize,TF_White,"Color Model = Unknown   ");
  272.     return 0;
  273. }
  274.  
  275. void show_hist(int x0,int y0,long *hist,float power)
  276. {
  277.     int i,height;
  278.     long max;
  279.     float norm;
  280. /*..........................................................................*/
  281. /*         Find max HIST[] value for auto scaling.                          */
  282. /*..........................................................................*/
  283.     max = 0;
  284.     for(i=0;i<256;i++)
  285.         if(hist[i] > max)
  286.             max = hist[i];
  287.     if(max !=0)
  288.         norm = 127.0/pow(max,power);
  289. /*..........................................................................*/
  290. /*         Clear histogram display.                                         */
  291. /*..........................................................................*/
  292.     vsa_set_color(TF_Black);
  293.     vsa_move_to(x0,y0);
  294.     vsa_rect_fill(x0+255,y0+127);
  295. /*..........................................................................*/
  296. /*         Draw box                                                         */
  297. /*..........................................................................*/
  298.     vsa_set_color(TF_White);
  299.     vsa_move_to(x0-1,y0-1);
  300.     vsa_rect(x0+256,y0+128);
  301.     vsa_set_viewport(x0,y0,x0+255,y0+127);
  302. /*..........................................................................*/
  303. /*  Draw histogram within box area.  Use a log scale for vertical axis.     */
  304. /*..........................................................................*/
  305.     vsa_set_color(TF_Orange);
  306.     for(i=0;i<256;i++)
  307.         {
  308.             if(hist[i] !=0)
  309.                 height = y0+127-norm*pow(hist[i],power);
  310.             else
  311.                 height = y0+127;
  312.             vsa_move_to(x0+i,y0+127);
  313.             vsa_line_to(x0+i,height);
  314.         }
  315.     vsa_set_viewport(0,0,XResolution-1,YResolution-1);
  316.     return;
  317. }
  318.  
  319.  
  320. /*........................ HIST_IMAGE.C ........... 6-8-94 ....*/
  321. /* This routine computes the monochrome amplitude histogram of */
  322. /* an image defined by the 'image' array.  The data in 'image' */
  323. /* is 8 bits per  pixels so the 'hist' array is only 256       */
  324. /* elements deep.  Upon returning from this routine, each      */
  325. /* element of 'hist' contains the count (or frequency) of      */
  326. /* occurance of pixels in the image with amplitude defined by  */
  327. /* the index of that element.  The histogram is computed by    */
  328. /* taking into account the values in the Color Look Up Table   */
  329. /* (CLUT).  Therefore, this routine works with all 8 bit image,*/
  330. /* not just gray scale ones with linear CLUTs.                 */
  331. /*    If 'mode' = 0, the pixel amplitude is computed as the    */
  332. /* Root of the Sum of the Squares (RSS) of R, G, and B.        */
  333. /* Otherwise its computed as the max of R, G, or B.            */
  334. /*                                                             */
  335. /* NOTE:  Where ever you see 0.5 being added in a calculation, */
  336. /*        the reason is so that the results are rounded to the */
  337. /*        nearest integer.                                     */
  338. /*.............................................................*/
  339. void hist_image(unsigned char huge *image,
  340.                                 unsigned char *lut,long *hist, int mode)
  341. {
  342.     int width,height,i,j,amp;
  343.     long n;
  344.     long temp[256];
  345.     float f_amp,red,grn,blu;
  346.     n = 0;
  347. /*.............................................................*/
  348. /*    Read out the width and Height of image.                  */
  349. /*.............................................................*/
  350.     width  = *((int huge *)image);
  351.     image += 2;
  352.     height = *((int huge *)image);
  353.     image += 2;
  354. /*.............................................................*/
  355. /*    Clear out TEMP array                                     */
  356. /*.............................................................*/
  357.     for(i=0;i<256;i++)
  358.         temp[i] = 0;
  359. /*.............................................................*/
  360. /*    Clear out HIST array                                     */
  361. /*.............................................................*/
  362.     for(i=0;i<256;i++)
  363.         hist[i] = 0;
  364. /*.............................................................*/
  365. /*    Now compute the total pixel count per CLUT address       */
  366. /*   (temp[i]).                                                */
  367. /*.............................................................*/
  368.     for(j=0;j<height;j++)
  369.         for(i=0;i<width;i++)
  370.             {
  371.                 temp[image[n]]++;
  372.                 n++;
  373.             }
  374. /*.............................................................*/
  375. /*    Now compute histogram.  Do so by computing an average    */
  376. /* amplitude (amp) for each CLUT entry (i).  Then take the     */
  377. /* total number of pixels for each CLUT entry (temp[i]) and    */
  378. /* add it to the histogram array (hist[amp]).                  */
  379. /*.............................................................*/
  380.     for(i=0;i<256;i++)
  381.         {
  382.             red = lut[3*i+0];
  383.             grn = lut[3*i+1];
  384.             blu = lut[3*i+2];
  385. /*.....    if mode = 0, Amplitude = SQRT(R^2+G^2+B^2)     .....*/
  386.             if(mode == 0)
  387.                 {
  388.                     f_amp = 255.0*sqrt(red*red+grn*grn+blu*blu)/109.2;
  389.                     amp = (int)(f_amp+0.5);
  390.                 }
  391. /*.....    if mode = 1, Amplitude = MAX of R, G, or B     .....*/
  392.             else
  393.                 {
  394.                     amp = red;
  395.                     if(grn > amp)
  396.                         amp = grn;
  397.                     if(blu > amp)
  398.                         amp = blu;
  399. /*.....  increase range scale: 0 thru 255 (was 0 to 63)   .....*/
  400.                     amp = 4.05*(float)amp;
  401.          }
  402.             hist[amp] += temp[i];
  403.         }
  404.     return;
  405. }                             /*.... END hist_image       .....*/
  406.  
  407. /*..................... HIST_DISPLAY.C ............ 6-8-94 ....*/
  408. /* This routine computes the monochrome amplitude histogram of */
  409. /* an image defined by the display contained within the 'x0,y0'*/
  410. /* to 'x1,y1' screen rectangle.  The data in 'image' is 8 bits */
  411. /* per  pixels so the 'hist' array is only 256 elements deep.  */
  412. /* Upon returning from this routine, each element of 'hist'    */
  413. /* contains the count (or frequency) of occurance of pixels in */
  414. /* the image with amplitude defined by the index of that       */
  415. /* element.                                                    */
  416. /*   The histogram is computed by taking into account the      */
  417. /* values in the Color Look Up Table (CLUT).  Therefore, this  */
  418. /* routine works with all 8 bit image, not just gray scale ones*/
  419. /* with linear CLUTs.                                          */
  420. /*    If 'mode' = 0, the pixel amplitude is computed as the    */
  421. /* Root of the Sum of the Squares (RSS) of R, G, and B.        */
  422. /* Otherwise its computed as the max of R, G, or B.            */
  423. /*                                                             */
  424. /* NOTE:  Where ever you see 0.5 being added in a calculation, */
  425. /*        the reason is so that the results are rounded to the */
  426. /*        nearest integer.                                     */
  427. /*.............................................................*/
  428. void hist_display(int x0, int y0, int x1, int y1,
  429.                                     unsigned char *lut, long *hist, int mode)
  430. {
  431.     unsigned char array[1280];
  432.     int width,i,j,amp;
  433.     long temp[256];
  434.     float f_amp,red,grn,blu;
  435. /*.............................................................*/
  436. /*     Compute the width of image.                             */
  437. /*.............................................................*/
  438.     width  = x1 - x0 + 1;
  439. /*.............................................................*/
  440. /*    Clear out TEMP array                                     */
  441. /*.............................................................*/
  442.     for(i=0;i<256;i++)
  443.         temp[i] = 0;
  444. /*.............................................................*/
  445. /*    Clear out HIST array                                     */
  446. /*.............................................................*/
  447.     for(i=0;i<256;i++)
  448.         hist[i] = 0;
  449. /*.............................................................*/
  450. /*    Now compute the total pixel count per CLUT address       */
  451. /*   (temp[i]).                                                */
  452. /*.............................................................*/
  453.     for(j=y0;j<y1+1;j++)
  454.         {
  455.             vsa_get_raster_line(x0,x1,j,array);
  456.             for(i=0;i<width;i++)
  457.                 temp[array[i]]++;
  458.         }
  459. /*.............................................................*/
  460. /*    Now compute histogram.  Do so by computing an average    */
  461. /* amplitude (amp) for each CLUT entry (i).  Then take the     */
  462. /* total number of pixels for each CLUT entry (temp[i]) and add*/
  463. /* it to the histogram array (hist[amp]).                      */
  464. /*.............................................................*/
  465.     for(i=0;i<256;i++)
  466.         {
  467.             red = lut[3*i+0];
  468.             grn = lut[3*i+1];
  469.             blu = lut[3*i+2];
  470. /*.....    if mode = 0, Amplitude = SQRT(R^2+G^2+B^2)     .....*/
  471.             if(mode == 0)
  472.                 {
  473.                     f_amp = 255.0*sqrt(red*red+grn*grn+blu*blu)/109.2;
  474.                     amp = (int)(f_amp+0.5);
  475.                 }
  476. /*.....    if mode = 1, Amplitude = MAX of R, G, or B     .....*/
  477.             else
  478.                 {
  479.                     amp = red;
  480.                     if(grn > amp)
  481.                         amp = grn;
  482.                     if(blu > amp)
  483.                         amp = blu;
  484. /*.....  increase range scale: 0 thru 255 (was 0 to 63)   .....*/
  485.                     amp = 4.05*(float)amp;
  486.                 }
  487.             hist[amp] += temp[i];
  488.         }
  489.     return;
  490. }                             /*.... END hist_display     .....*/
  491.  
  492. /*........................... HISTEQ.C ........... 6-8-94 .....*/
  493. /* This routine performs the Histogram Equalization process.   */
  494. /* When calling this routine 'lut' holds the current image look*/
  495. /* up table, and 'hist' holds the current image histogram.     */
  496. /* both 'lut' and 'hist' are updated with the new values prior */
  497. /* to returning to the calling routine.  Note that the image's */
  498. /* stored pixel values are not affected by equalization.       */
  499. /*    The strength parameter 'n' determines how equalization   */
  500. /* distribute pixels.  A value of 0.0 preserves the original   */
  501. /* pixel density profile while spreading it to fit between     */
  502. /* pixel amplitude 0 and pixel amplitude 255.  A stength of 1.0*/
  503. /* results in uniform pixel distribution (like comercial       */
  504. /* software packages).                                         */
  505. /*    If 'mode' = 0, the pixel amplitude is computed as the    */
  506. /* Root of the Sum of the Squares (RSS) of R, G, and B.        */
  507. /* Otherwise its computed as the max of R, G, or B.            */
  508. /*                                                             */
  509. /* NOTE:  Where ever you see 0.5 being added in a calculation, */
  510. /*        the reason is so that the results are rounded to the */
  511. /*        nearest integer.                                     */
  512. /*.............................................................*/
  513. void histeq(unsigned char *lut, long *hist,double n,
  514.                         int mode)
  515. {
  516.     int i,amp,max_amp;
  517.     float norm,scale[256],factor,f_amp,red,grn,blu;
  518.     unsigned temp[256];
  519. /*.............................................................*/
  520. /* Generate the 'scale' array such that for a given index (i)  */
  521. /* into the array (corresponding to a pixel amplitude of i)    */
  522. /* the 'scale[i]' value is the cumulative sum of number of     */
  523. /* pixels whose amplitude are 'i' or less (the sum is          */
  524. /* discounted or inflated by the strength factor 'n').         */
  525. /*    Also clear out 'temp[]' so it can be updated later.      */
  526. /*.............................................................*/
  527.     if(hist[0] !=0)
  528.         scale[0] = pow(hist[0],n);
  529.     else
  530.         scale[0] = 0;
  531.     for(i=1;i<256;i++)
  532.         {
  533.             if(hist[i] !=0)
  534.                 scale[i] = scale[i-1] + pow(hist[i],n);
  535.             else
  536.                 scale[i] = scale[i-1];
  537.         }
  538.     for(i=0;i<256;i++)
  539.         temp[i] = 0;
  540. /*.............................................................*/
  541. /*    Normalize 'scale' array so that max value is 255.0       */
  542. /*.............................................................*/
  543.     norm = 255.0/scale[255];
  544.     for(i=0;i<256;i++)
  545.         scale[i] *= norm;
  546. /*.............................................................*/
  547. /*    Perform the equalization by "shifting" each CLUT entry   */
  548. /* brightness level up or down such that for a pixel of        */
  549. /* amplitude AMP, its new amplitude will be equal to           */
  550. /* 'scale[AMP]'.                                               */
  551. /*.............................................................*/
  552.     for(i=0;i<256;i++)
  553.         {
  554.             red = lut[3*i+0];
  555.             grn = lut[3*i+1];
  556.             blu = lut[3*i+2];
  557. /*.....    if mode = 0, Amplitude = SQRT(R^2+G^2+B^2)     .....*/
  558.             if(mode == 0)
  559.                 {
  560.                     f_amp = 255.0*sqrt(red*red+grn*grn+blu*blu)/109.2;
  561.                     amp = (int)(f_amp+0.5);
  562.                 }
  563. /*.....    if mode = 1, Amplitude = MAX of R, G, or B     .....*/
  564.             else
  565.                 {
  566.                     max_amp = red;
  567.                     if(grn > max_amp)
  568.                         max_amp = grn;
  569.                     if(blu > max_amp)
  570.                         max_amp = blu;
  571. /*.....  increase range scale: 0 thru 255 (was 0 to 63)   .....*/
  572.                     amp = 4.05*(float)max_amp;
  573.                 }
  574.  
  575. /*.............................................................*/
  576. /* Figure a scale factor such that pixels of amplitude AMP will*/
  577. /* have a new amplitude equal to 'scale[AMP]'.                 */
  578. /*.............................................................*/
  579.             if(amp != 0)
  580.                 factor = scale[amp]/(float)amp;
  581.             else
  582.                 factor = 0;
  583. /*.............................................................*/
  584. /*   Now scale red, green, and blue amplitudes by the computed */
  585. /* scale factor.  In 'mode' = 0, it is possible that the factor*/
  586. /* will cause one of these color values to exceed 63.  In this */
  587. /* case the values are clamped to 63.This will  cause some     */
  588. /* minor color drift in the  brighter non white pixels  but it */
  589. /* should not be noticable.  The alternative would be to scale */
  590. /* down the brightness of the whole pixel, or the whole image. */
  591. /* Neither of these two options seemed any more desirable.     */
  592. /*.............................................................*/
  593.             lut[3*i+0] = (int)((float)lut[3*i+0]*factor + 0.5);
  594.             lut[3*i+1] = (int)((float)lut[3*i+1]*factor + 0.5);
  595.             lut[3*i+2] = (int)((float)lut[3*i+2]*factor + 0.5);
  596.             if(lut[3*i+0] > 63) lut[3*i+0] = 63;
  597.             if(lut[3*i+1] > 63) lut[3*i+1] = 63;
  598.             if(lut[3*i+2] > 63) lut[3*i+2] = 63;
  599.             temp[(int)(factor*amp+0.5)] += hist[amp];
  600.         }
  601. /*.............................................................*/
  602. /*Update histogram array with new, equalized, histogram values.*/
  603. /*.............................................................*/
  604.     for(i=0;i<256;i++)
  605.         hist[i] = temp[i];
  606.     return;
  607. }                            /*.... END histeq            .....*/
  608.  
  609. void color_bar(x0,y0)
  610. int x0,y0;
  611. {
  612.     int i;
  613.     unsigned xx,yy,a,b;
  614.     float c;
  615.     xx = XResolution;
  616.     yy = YResolution;
  617. /*..........................................................................*/
  618. /*     Draw outline for color bar.                                          */
  619. /*..........................................................................*/
  620.     vsa_set_color(15);
  621.     vsa_move_to(x0-1,y0-1);
  622.     a = .75*xx;
  623.     b = .065*yy;
  624.     vsa_rect(x0+a+1,y0+b+1);
  625.     c = (float)a/256;
  626.     for(i=0;i<256;i++)
  627.         {
  628.             vsa_set_color((unsigned char)i);
  629.             vsa_move_to(x0+(unsigned)(i*c),y0);
  630.             vsa_rect_fill(x0+(unsigned)(c+i*c),y0+b);
  631.         }
  632.     return;
  633. }
  634.  
  635. void update_message(int x0,int y0,int color,char *text)
  636. {
  637.     clear_text_area(x0,y0,51,TF_Black);
  638.     vsa_write_string(x0,y0,color,text);
  639.     vsa_set_color(color);
  640.     return;
  641. }
  642.  
  643. void clear_text_area(int x0,int y0,int length,int color)
  644. {
  645.     vsa_set_color(color);
  646.     vsa_move_to(x0,y0);
  647.     vsa_rect_fill(x0+length*XCharSize-1,y0+YCharSize-1);
  648.     return;
  649. }
  650.  
  651. /*.......................... VSA_GET_INPUT .................... 6-25-94 ....*/
  652. /*  This routine reads the keyboard input and echos it to the screen until  */
  653. /* a carriage return is entered. Then the whole text string is returned     */
  654. /* via 'text'.                                                              */
  655. /*..........................................................................*/
  656. void vsa_get_input(char *text)
  657. {
  658.     int i,x,y;
  659.     char key;
  660.     vsa_get_text_cursor(&x,&y);
  661.     i=0;
  662.     text[0] = 0;
  663.     while((key = getch()) != 13)               /*  Do until a return is hit.  */
  664.         {
  665.             if(key != 8)
  666.                 {                                    /*  If not a back space        */
  667.                     text[i] = key;                     /*  add key entry to string.   */
  668.                     text[i+1] = 0;
  669.                     vsa_write_string(x,y,TF_White,text);/*  Echo the updated string.   */
  670.                     i++;
  671.                 }
  672.             else
  673.                 {                                    /*  If a back space            */
  674.                     if(i > 0) i --;                    /*  delete last key entry.     */
  675.                     text[i] = 92;
  676.                     vsa_write_string(x,y,TF_White,text);/*  Echo the updated string.   */
  677.                     text[i] = 0;
  678.                 }
  679.         }
  680.     return;
  681. }
  682.  
  683. void error_message(int stage,int error,int col,int row)
  684. {
  685.     int x,y;
  686.     x = col*XCharSize;
  687.     y = row*YCharSize;
  688.     if(stage == 0)
  689.         {
  690.             if(error == 1)
  691.                 update_message(x,y,TF_Red,"File Read Error!                            ");
  692.             if(error == 2)
  693.                 update_message(x,y,TF_Red,"File Shorter Than Expected!                 ");
  694.             if(error == 3)
  695.                 update_message(x,y,TF_Red,"Bad TIFF File!                              ");
  696.         }
  697.     if(stage == 1)
  698.         {
  699.             if(error == 1)
  700.                 update_message(x,y,TF_Red,"NULL TIFF file Pointer!                      ");
  701.             if(error == 2)
  702.                 update_message(x,y,TF_Red,"Error Seeking in File!                       ");
  703.             if(error == 3)
  704.                 update_message(x,y,TF_Red,"File Read error!                             ");
  705.             if(error == 4)
  706.                 update_message(x,y,TF_Red,"Greater than 8 Bit Palette Pixels Not Supported!");
  707.             if(error == 5)
  708.                 update_message(x,y,TF_Red,"Samples Per Pixel > 3 Not Supported!         ");
  709.             if(error == 6)
  710.                 update_message(x,y,TF_Red,"Only 8x8x8 Bit True Color Pixels Supported!  ");
  711.             if(error == 7)
  712.                 update_message(x,y,TF_Red,"Compressed TIFF data Not Supported!          ");
  713.             if(error == 8)
  714.                 update_message(x,y,TF_Red,"This Photometric Interpretation Not Supported!");
  715.             if(error == 9)
  716.                 update_message(x,y,TF_Red,"Currently Only Support up to 1024 Strips!    ");
  717.             if(error == 10)
  718.                 update_message(x,y,TF_Red,"Samples Per Pixel > 3 Not Supported!         ");
  719.             if(error == 11)
  720.                 update_message(x,y,TF_Red,"Currently Only Support up to 1024 Strips!    ");
  721.             if(error == 12)
  722.                 update_message(x,y,TF_Red,"This Planar Configuration Not Supported!     ");
  723.             if(error == 13)
  724.                 update_message(x,y,TF_Red,"This Predictor Not Supported!                ");
  725.             if(error == 14)
  726.                 update_message(x,y,TF_Red,"Color Map Size > 256 Not Supported!          ");
  727.         }
  728.     return;
  729. }
  730.